/*
 * Copyright 2014 JootMir Project
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * Support: http://www.jootmir.org
 */
package org.jootmir.client.core.texture.loader;

import java.nio.ByteBuffer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

import org.apache.log4j.Logger;
import org.jootmir.client.core.exception.JMir2Exception;
import org.jootmir.client.core.texture.Texture;
import org.lwjgl.opengl.EXTTextureMirrorClamp;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;

/**
 * 纹理加载任务 <br>
 * 即实际上处理纹理加载的线程主函数承载对象 <br>
 * 会不会太专业了(-_-)
 * 
 * @author ShawRyan
 */
public class TextureLoadingTask {
	/** log */
	private static final Logger log = Logger.getLogger(TextureLoadingTask.class);

	/** 纹理加载器 */
	private TextureLoaderHandler tlh;
	/** 纹理索引 */
	private Integer index = null;
	/** 加载任务 */
	private Future<ByteBuffer> loadFuture = null;
	/** 线程池 */
	private ExecutorService threadPool = null;
	/** 纹理 */
	private Texture tex = null;

	/**
	 * 构造函数 <br>
	 * 使用纹理索引来加载纹理 <br>
	 * 如纹理图片信息未加入缓存，则可只给出纹理索引
	 * 
	 * @param index
	 *            纹理索引
	 * @param threadPool
	 *            执行线程池
	 */
	public TextureLoadingTask(Integer index, Class<? extends TextureLoaderHandler> infoClz, ExecutorService threadPool) {
		this.index = index;
		this.threadPool = threadPool;
		try {
			this.tlh = infoClz.newInstance();
			this.tlh.fromIndexRef(index);
		} catch (InstantiationException | IllegalAccessException ex) {
			JMir2Exception exception = JMir2Exception.valueOf(ex, JMir2Exception.EXCEPTION_TYPE_CALC);
			log.error(exception.getMessage(), ex);
			throw exception;
		}
	}

	/**
	 * 构造函数 <br>
	 * 在图片信息被缓存时使用此种构造函数，减轻程序读取压力
	 * 
	 * @param index
	 *            纹理索引
	 * @param wii
	 *            纹理图片描述信息
	 * @param threadPool
	 *            执行线程池
	 */
	public TextureLoadingTask(Integer index, TextureLoaderHandler wii, ExecutorService threadPool) {
		this.index = index;
		this.threadPool = threadPool;
		this.tlh = wii;
	}

	/**
	 * 加载纹理
	 * 
	 * @return 是否完成加载
	 */
	public boolean update() {
		if (loadFuture == null)
			loadFuture = threadPool.submit(tlh);
		else if (loadFuture.isDone()) {
			try {
				ByteBuffer datas = loadFuture.get();
				/* 绑定数据 */
				tex = new Texture2DImpl(GL11.glGenTextures(), tlh.getWidth(), tlh.getHeight(), index);
				GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
				GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
				if (GLContext.getCapabilities().GL_EXT_texture_mirror_clamp) {
					GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S,
							EXTTextureMirrorClamp.GL_MIRROR_CLAMP_TO_EDGE_EXT);
					GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T,
							EXTTextureMirrorClamp.GL_MIRROR_CLAMP_TO_EDGE_EXT);
				} else {
					GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP);
					GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);
				}

				// 绑定纹理数据到纹理id
				tex.bind();
				GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, tlh.getWidth(), tlh.getHeight(), 0, GL11.GL_RGBA,
						GL11.GL_UNSIGNED_BYTE, datas);
			} catch (Exception ex) {
				JMir2Exception exception = JMir2Exception.valueOf(ex, JMir2Exception.EXCEPTION_TYPE_CALC);
				log.error(exception.getMessage(), ex);
				throw exception;
			}
		}
		return tex != null;
	}

	/** 本次加载得到的图片信息 */
	public TextureLoaderHandler getImageInfo() {
		return tlh;
	}

	/** 获取纹理索引 */
	public Integer getIndex() {
		return index;
	}

	/** 读取加载的纹理 */
	public Texture getTex() {
		return tex;
	}

	/**
	 * 纹理贴图
	 * 
	 * @author ShawRyan
	 *
	 */
	public class Texture2DImpl implements Texture {

		/** 宽度 */
		private int width;
		/** 高度 */
		private int height;
		/** 索引 */
		private Integer ref;
		/** 纹理ID */
		private int textureId;

		Texture2DImpl() {
		}

		Texture2DImpl(int textureId, int width, int height, Integer ref) {
			this.textureId = textureId;
			this.width = width;
			this.height = height;
			this.ref = ref;
		}

		public Integer getTextureRef() {
			return this.ref;
		}

		public void bind() {
			GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.textureId);
		}

		public void release() {
			/*
			 * ByteBuffer temp = ByteBuffer.allocateDirect(4);
			 * temp.order(ByteOrder.nativeOrder()); IntBuffer texBuf =
			 * temp.asIntBuffer(); texBuf.put(this.textureId); texBuf.flip();
			 * glDeleteTextures(texBuf);
			 */
			GL11.glDeleteTextures(this.textureId);
		}

		public int getHeight() {
			return this.height;
		}

		public int getWidth() {
			return this.width;
		}

		public int getTextureID() {
			return this.textureId;
		}
	}
}